package com.miao.rggateway.filter;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import com.caifeng.domain.ResponseCode;
import com.caifeng.domain.ResponseResult;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class JwtGlobalFilter implements GlobalFilter {

    @Value("${jwt.secret}")
    private String secret;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        // 检查请求路径是否包含"/auth"，如果是，则直接执行下一个过滤器
        if (request.getURI().getPath().contains("/auth")) {
            return chain.filter(exchange);
        }
        ServerHttpResponse response = exchange.getResponse();
        // 从请求头中获取Authorization令牌
        String token = request.getHeaders().getFirst("Authorization");
        if (token == null || !JWTUtil.verify(token, secret.getBytes())) {
            ResponseResult result = new ResponseResult(ResponseCode.TOKEN_INVALIDATION, "token无效");
            return response.writeWith(Mono.just(response.bufferFactory().wrap(JSONUtil.toJsonStr(result).getBytes())));
        }
        try {
            JWT jwt = JWTUtil.parseToken(token);
            JWTValidator.of(jwt).validateDate();
            String userId = jwt.getPayload("user_id").toString();
            String permissions = redisTemplate.opsForValue().getAndExpire("USER:" + userId, 1, TimeUnit.HOURS);
            if (permissions == null) {
                ResponseResult result = new ResponseResult(ResponseCode.NOT_LOGIN);
                return response.writeWith(Mono.just(response.bufferFactory().wrap(JSONUtil.toJsonStr(result).getBytes())));
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put("user_id", userId);
                // 去除首尾的[]
                map.put("permissions", permissions.substring(1, permissions.length() - 1));
                String finalToken = JWTUtil.createToken(map, secret.getBytes());
                ServerHttpRequest serverHttpRequest = request.mutate().headers(h -> h.add("Authorization", finalToken)).build();
                exchange.mutate().request(serverHttpRequest);
            }
        } catch (ValidateException e) {
            ResponseResult result = new ResponseResult(ResponseCode.TOKEN_INVALIDATION, "token过期");
            return response.writeWith(Mono.just(response.bufferFactory().wrap(JSONUtil.toJsonStr(result).getBytes())));
        }
        return chain.filter(exchange);
    }
}